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
ae72d71d
Commit
ae72d71d
authored
Nov 08, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add latest changes from gitlab-org/gitlab@master
parent
759bab05
Changes
71
Hide whitespace changes
Inline
Side-by-side
Showing
71 changed files
with
1270 additions
and
251 deletions
+1270
-251
app/controllers/application_controller.rb
app/controllers/application_controller.rb
+5
-5
app/controllers/concerns/confirm_email_warning.rb
app/controllers/concerns/confirm_email_warning.rb
+5
-2
app/controllers/concerns/uploads_actions.rb
app/controllers/concerns/uploads_actions.rb
+17
-0
app/controllers/projects/environments_controller.rb
app/controllers/projects/environments_controller.rb
+1
-1
app/controllers/projects/error_tracking_controller.rb
app/controllers/projects/error_tracking_controller.rb
+63
-4
app/controllers/uploads_controller.rb
app/controllers/uploads_controller.rb
+1
-1
app/helpers/application_settings_helper.rb
app/helpers/application_settings_helper.rb
+1
-1
app/helpers/projects/error_tracking_helper.rb
app/helpers/projects/error_tracking_helper.rb
+9
-0
app/models/application_setting_implementation.rb
app/models/application_setting_implementation.rb
+3
-2
app/models/error_tracking/project_error_tracking_setting.rb
app/models/error_tracking/project_error_tracking_setting.rb
+20
-0
app/serializers/error_tracking/detailed_error_entity.rb
app/serializers/error_tracking/detailed_error_entity.rb
+27
-0
app/serializers/error_tracking/detailed_error_serializer.rb
app/serializers/error_tracking/detailed_error_serializer.rb
+7
-0
app/serializers/error_tracking/error_event_entity.rb
app/serializers/error_tracking/error_event_entity.rb
+7
-0
app/serializers/error_tracking/error_event_serializer.rb
app/serializers/error_tracking/error_event_serializer.rb
+7
-0
app/services/error_tracking/base_service.rb
app/services/error_tracking/base_service.rb
+66
-0
app/services/error_tracking/issue_details_service.rb
app/services/error_tracking/issue_details_service.rb
+15
-0
app/services/error_tracking/issue_latest_event_service.rb
app/services/error_tracking/issue_latest_event_service.rb
+15
-0
app/services/error_tracking/list_issues_service.rb
app/services/error_tracking/list_issues_service.rb
+7
-39
app/services/error_tracking/list_projects_service.rb
app/services/error_tracking/list_projects_service.rb
+23
-29
app/views/admin/application_settings/_snowplow.html.haml
app/views/admin/application_settings/_snowplow.html.haml
+2
-2
app/views/layouts/nav/sidebar/_project.html.haml
app/views/layouts/nav/sidebar/_project.html.haml
+2
-0
app/views/projects/environments/empty_logs.html.haml
app/views/projects/environments/empty_logs.html.haml
+14
-0
app/views/projects/environments/empty_metrics.html.haml
app/views/projects/environments/empty_metrics.html.haml
+2
-2
app/views/projects/error_tracking/details.html.haml
app/views/projects/error_tracking/details.html.haml
+3
-0
changelogs/unreleased/31222-follow-up-from-adjusts-snowplow-to-use-cookies-for-sessions.yml
...-up-from-adjusts-snowplow-to-use-cookies-for-sessions.yml
+5
-0
changelogs/unreleased/32052-add-pa-start-date-limit.yml
changelogs/unreleased/32052-add-pa-start-date-limit.yml
+5
-0
changelogs/unreleased/32464-backend-sentry-error-details.yml
changelogs/unreleased/32464-backend-sentry-error-details.yml
+5
-0
config/routes/project.rb
config/routes/project.rb
+10
-0
db/migrate/20191004080818_add_productivity_analytics_start_date.rb
...e/20191004080818_add_productivity_analytics_start_date.rb
+11
-0
db/migrate/20191004081520_fill_productivity_analytics_start_date.rb
.../20191004081520_fill_productivity_analytics_start_date.rb
+31
-0
db/migrate/20191028184740_rename_snowplow_site_id_to_snowplow_app_id.rb
...91028184740_rename_snowplow_site_id_to_snowplow_app_id.rb
+17
-0
db/post_migrate/20191029095537_cleanup_application_settings_snowplow_site_id_rename.rb
...7_cleanup_application_settings_snowplow_site_id_rename.rb
+17
-0
db/schema.rb
db/schema.rb
+2
-1
doc/api/settings.md
doc/api/settings.md
+1
-1
doc/ci/yaml/README.md
doc/ci/yaml/README.md
+1
-0
lib/api/merge_requests.rb
lib/api/merge_requests.rb
+5
-2
lib/api/settings.rb
lib/api/settings.rb
+1
-1
lib/gitlab/ci/config/entry/boolean.rb
lib/gitlab/ci/config/entry/boolean.rb
+20
-0
lib/gitlab/ci/config/entry/default.rb
lib/gitlab/ci/config/entry/default.rb
+6
-2
lib/gitlab/ci/config/entry/job.rb
lib/gitlab/ci/config/entry/job.rb
+4
-1
lib/gitlab/error_tracking/detailed_error.rb
lib/gitlab/error_tracking/detailed_error.rb
+31
-0
lib/gitlab/error_tracking/error_event.rb
lib/gitlab/error_tracking/error_event.rb
+11
-0
lib/gitlab/tracking.rb
lib/gitlab/tracking.rb
+2
-2
lib/sentry/client.rb
lib/sentry/client.rb
+97
-14
locale/gitlab.pot
locale/gitlab.pot
+18
-9
spec/controllers/application_controller_spec.rb
spec/controllers/application_controller_spec.rb
+6
-8
spec/controllers/projects/environments_controller_spec.rb
spec/controllers/projects/environments_controller_spec.rb
+2
-2
spec/controllers/projects/error_tracking_controller_spec.rb
spec/controllers/projects/error_tracking_controller_spec.rb
+191
-11
spec/controllers/uploads_controller_spec.rb
spec/controllers/uploads_controller_spec.rb
+12
-12
spec/db/schema_spec.rb
spec/db/schema_spec.rb
+1
-1
spec/factories/error_tracking/detailed_error.rb
spec/factories/error_tracking/detailed_error.rb
+29
-0
spec/factories/error_tracking/error_event.rb
spec/factories/error_tracking/error_event.rb
+18
-0
spec/features/projects/members/member_leaves_project_spec.rb
spec/features/projects/members/member_leaves_project_spec.rb
+1
-1
spec/fixtures/api/schemas/error_tracking/error.json
spec/fixtures/api/schemas/error_tracking/error.json
+17
-3
spec/fixtures/api/schemas/error_tracking/error_detailed.json
spec/fixtures/api/schemas/error_tracking/error_detailed.json
+45
-0
spec/fixtures/api/schemas/error_tracking/error_stack_trace.json
...ixtures/api/schemas/error_tracking/error_stack_trace.json
+14
-0
spec/fixtures/api/schemas/error_tracking/issue_detailed.json
spec/fixtures/api/schemas/error_tracking/issue_detailed.json
+11
-0
spec/fixtures/api/schemas/error_tracking/issue_stack_trace.json
...ixtures/api/schemas/error_tracking/issue_stack_trace.json
+11
-0
spec/helpers/application_settings_helper_spec.rb
spec/helpers/application_settings_helper_spec.rb
+1
-1
spec/lib/gitlab/ci/config/entry/default_spec.rb
spec/lib/gitlab/ci/config/entry/default_spec.rb
+1
-1
spec/lib/gitlab/ci/config/entry/job_spec.rb
spec/lib/gitlab/ci/config/entry/job_spec.rb
+1
-1
spec/lib/gitlab/ci/yaml_processor_spec.rb
spec/lib/gitlab/ci/yaml_processor_spec.rb
+19
-0
spec/lib/gitlab/tracking_spec.rb
spec/lib/gitlab/tracking_spec.rb
+1
-1
spec/migrations/fill_productivity_analytics_start_date_spec.rb
...migrations/fill_productivity_analytics_start_date_spec.rb
+39
-0
spec/requests/api/settings_spec.rb
spec/requests/api/settings_spec.rb
+1
-1
spec/requests/user_avatar_spec.rb
spec/requests/user_avatar_spec.rb
+36
-0
spec/services/error_tracking/issue_details_service_spec.rb
spec/services/error_tracking/issue_details_service_spec.rb
+48
-0
spec/services/error_tracking/issue_latest_event_service_spec.rb
...ervices/error_tracking/issue_latest_event_service_spec.rb
+48
-0
spec/services/error_tracking/list_issues_service_spec.rb
spec/services/error_tracking/list_issues_service_spec.rb
+5
-86
spec/services/error_tracking/list_projects_service_spec.rb
spec/services/error_tracking/list_projects_service_spec.rb
+1
-1
spec/support/shared_examples/services/error_tracking_service_shared_examples.rb
...amples/services/error_tracking_service_shared_examples.rb
+89
-0
No files found.
app/controllers/application_controller.rb
View file @
ae72d71d
...
...
@@ -20,11 +20,11 @@ class ApplicationController < ActionController::Base
before_action
:authenticate_user!
,
except:
[
:route_not_found
]
before_action
:enforce_terms!
,
if: :should_enforce_terms?
before_action
:validate_user_service_ticket!
before_action
:check_password_expiration
before_action
:check_password_expiration
,
if: :html_request?
before_action
:ldap_security_check
before_action
:sentry_context
before_action
:default_headers
before_action
:add_gon_variables
,
unless:
[
:peek_request?
,
:json_request?
]
before_action
:add_gon_variables
,
if: :html_request?
before_action
:configure_permitted_parameters
,
if: :devise_controller?
before_action
:require_email
,
unless: :devise_controller?
before_action
:active_user_check
,
unless: :devise_controller?
...
...
@@ -455,8 +455,8 @@ class ApplicationController < ActionController::Base
response
.
headers
[
'Page-Title'
]
=
URI
.
escape
(
page_title
(
'GitLab'
))
end
def
peek
_request?
request
.
path
.
start_with?
(
'/-/peek'
)
def
html
_request?
request
.
format
.
html?
end
def
json_request?
...
...
@@ -466,7 +466,7 @@ class ApplicationController < ActionController::Base
def
should_enforce_terms?
return
false
unless
Gitlab
::
CurrentSettings
.
current_application_settings
.
enforce_terms
!
(
peek_request?
||
devise_controller?
)
html_request?
&&
!
devise_controller?
end
def
set_usage_stats_consent_flag
...
...
app/controllers/concerns/confirm_email_warning.rb
View file @
ae72d71d
...
...
@@ -4,15 +4,18 @@ module ConfirmEmailWarning
extend
ActiveSupport
::
Concern
included
do
before_action
:set_confirm_warning
,
if:
->
{
Feature
.
enabled?
(
:soft_email_confirmation
)
}
before_action
:set_confirm_warning
,
if:
:show_confirm_warning?
end
protected
def
show_confirm_warning?
html_request?
&&
request
.
get?
&&
Feature
.
enabled?
(
:soft_email_confirmation
)
end
def
set_confirm_warning
return
unless
current_user
return
if
current_user
.
confirmed?
return
if
peek_request?
||
json_request?
||
!
request
.
get?
email
=
current_user
.
unconfirmed_email
||
current_user
.
email
...
...
app/controllers/concerns/uploads_actions.rb
View file @
ae72d71d
# frozen_string_literal: true
module
UploadsActions
extend
ActiveSupport
::
Concern
include
Gitlab
::
Utils
::
StrongMemoize
include
SendFileUpload
UPLOAD_MOUNTS
=
%w(avatar attachment file logo header_logo favicon)
.
freeze
included
do
prepend_before_action
:set_request_format_from_path_extension
end
def
create
uploader
=
UploadService
.
new
(
model
,
params
[
:file
],
uploader_class
).
execute
...
...
@@ -64,6 +69,18 @@ module UploadsActions
private
# From ActionDispatch::Http::MimeNegotiation. We have an initializer that
# monkey-patches this method out (so that repository paths don't guess a
# format based on extension), but we do want this behaviour when serving
# uploads.
def
set_request_format_from_path_extension
path
=
request
.
headers
[
'action_dispatch.original_path'
]
||
request
.
headers
[
'PATH_INFO'
]
if
match
=
path
&
.
match
(
/\.(\w+)\z/
)
request
.
format
=
match
.
captures
.
first
end
end
def
uploader_class
raise
NotImplementedError
end
...
...
app/controllers/projects/environments_controller.rb
View file @
ae72d71d
...
...
@@ -133,7 +133,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
if
environment
redirect_to
environment_metrics_path
(
environment
)
else
render
:empty
render
:empty
_metrics
end
end
...
...
app/controllers/projects/error_tracking_controller.rb
View file @
ae72d71d
...
...
@@ -15,6 +15,23 @@ class Projects::ErrorTrackingController < Projects::ApplicationController
end
end
def
details
respond_to
do
|
format
|
format
.
html
format
.
json
do
render_issue_detail_json
end
end
end
def
stack_trace
respond_to
do
|
format
|
format
.
json
do
render_issue_stack_trace_json
end
end
end
def
list_projects
respond_to
do
|
format
|
format
.
json
do
...
...
@@ -29,10 +46,7 @@ class Projects::ErrorTrackingController < Projects::ApplicationController
service
=
ErrorTracking
::
ListIssuesService
.
new
(
project
,
current_user
)
result
=
service
.
execute
unless
result
[
:status
]
==
:success
return
render
json:
{
message:
result
[
:message
]
},
status:
result
[
:http_status
]
||
:bad_request
end
return
if
handle_errors
(
result
)
render
json:
{
errors:
serialize_errors
(
result
[
:issues
]),
...
...
@@ -40,6 +54,28 @@ class Projects::ErrorTrackingController < Projects::ApplicationController
}
end
def
render_issue_detail_json
service
=
ErrorTracking
::
IssueDetailsService
.
new
(
project
,
current_user
,
issue_details_params
)
result
=
service
.
execute
return
if
handle_errors
(
result
)
render
json:
{
error:
serialize_detailed_error
(
result
[
:issue
])
}
end
def
render_issue_stack_trace_json
service
=
ErrorTracking
::
IssueLatestEventService
.
new
(
project
,
current_user
,
issue_details_params
)
result
=
service
.
execute
return
if
handle_errors
(
result
)
render
json:
{
error:
serialize_error_event
(
result
[
:latest_event
])
}
end
def
render_project_list_json
service
=
ErrorTracking
::
ListProjectsService
.
new
(
project
,
...
...
@@ -62,10 +98,21 @@ class Projects::ErrorTrackingController < Projects::ApplicationController
end
end
def
handle_errors
(
result
)
unless
result
[
:status
]
==
:success
render
json:
{
message:
result
[
:message
]
},
status:
result
[
:http_status
]
||
:bad_request
end
end
def
list_projects_params
params
.
require
(
:error_tracking_setting
).
permit
([
:api_host
,
:token
])
end
def
issue_details_params
params
.
permit
(
:issue_id
)
end
def
set_polling_interval
Gitlab
::
PollingInterval
.
set_header
(
response
,
interval:
POLLING_INTERVAL
)
end
...
...
@@ -76,6 +123,18 @@ class Projects::ErrorTrackingController < Projects::ApplicationController
.
represent
(
errors
)
end
def
serialize_detailed_error
(
error
)
ErrorTracking
::
DetailedErrorSerializer
.
new
(
project:
project
,
user:
current_user
)
.
represent
(
error
)
end
def
serialize_error_event
(
event
)
ErrorTracking
::
ErrorEventSerializer
.
new
(
project:
project
,
user:
current_user
)
.
represent
(
event
)
end
def
serialize_projects
(
projects
)
ErrorTracking
::
ProjectSerializer
.
new
(
project:
project
,
user:
current_user
)
...
...
app/controllers/uploads_controller.rb
View file @
ae72d71d
...
...
@@ -20,7 +20,7 @@ class UploadsController < ApplicationController
skip_before_action
:authenticate_user!
before_action
:upload_mount_satisfied?
before_action
:
find_
model
before_action
:model
before_action
:authorize_access!
,
only:
[
:show
]
before_action
:authorize_create_access!
,
only:
[
:create
,
:authorize
]
before_action
:verify_workhorse_api!
,
only:
[
:authorize
]
...
...
app/helpers/application_settings_helper.rb
View file @
ae72d71d
...
...
@@ -293,7 +293,7 @@ module ApplicationSettingsHelper
:snowplow_collector_hostname
,
:snowplow_cookie_domain
,
:snowplow_enabled
,
:snowplow_
site
_id
,
:snowplow_
app
_id
,
:snowplow_iglu_registry_url
,
:push_event_hooks_limit
,
:push_event_activities_limit
,
...
...
app/helpers/projects/error_tracking_helper.rb
View file @
ae72d71d
...
...
@@ -13,4 +13,13 @@ module Projects::ErrorTrackingHelper
'illustration-path'
=>
image_path
(
'illustrations/cluster_popover.svg'
)
}
end
def
error_details_data
(
project
,
issue
)
opts
=
[
project
,
issue
,
{
format: :json
}]
{
'issue-details-path'
=>
details_namespace_project_error_tracking_index_path
(
*
opts
),
'issue-stack-trace-path'
=>
stack_trace_namespace_project_error_tracking_index_path
(
*
opts
)
}
end
end
app/models/application_setting_implementation.rb
View file @
ae72d71d
...
...
@@ -132,11 +132,12 @@ module ApplicationSettingImplementation
snowplow_collector_hostname:
nil
,
snowplow_cookie_domain:
nil
,
snowplow_enabled:
false
,
snowplow_
site
_id:
nil
,
snowplow_
app
_id:
nil
,
snowplow_iglu_registry_url:
nil
,
custom_http_clone_url_root:
nil
,
pendo_enabled:
false
,
pendo_url:
nil
pendo_url:
nil
,
productivity_analytics_start_date:
Time
.
now
}
end
...
...
app/models/error_tracking/project_error_tracking_setting.rb
View file @
ae72d71d
...
...
@@ -87,10 +87,30 @@ module ErrorTracking
{
projects:
sentry_client
.
list_projects
}
end
def
issue_details
(
opts
=
{})
with_reactive_cache
(
'issue_details'
,
opts
.
stringify_keys
)
do
|
result
|
result
end
end
def
issue_latest_event
(
opts
=
{})
with_reactive_cache
(
'issue_latest_event'
,
opts
.
stringify_keys
)
do
|
result
|
result
end
end
def
calculate_reactive_cache
(
request
,
opts
)
case
request
when
'list_issues'
{
issues:
sentry_client
.
list_issues
(
**
opts
.
symbolize_keys
)
}
when
'issue_details'
{
issue:
sentry_client
.
issue_details
(
**
opts
.
symbolize_keys
)
}
when
'issue_latest_event'
{
latest_event:
sentry_client
.
issue_latest_event
(
**
opts
.
symbolize_keys
)
}
end
rescue
Sentry
::
Client
::
Error
=>
e
{
error:
e
.
message
,
error_type:
SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE
}
...
...
app/serializers/error_tracking/detailed_error_entity.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
DetailedErrorEntity
<
Grape
::
Entity
expose
:count
,
:culprit
,
:external_base_url
,
:external_url
,
:first_release_last_commit
,
:first_release_short_version
,
:first_seen
,
:frequency
,
:id
,
:last_release_last_commit
,
:last_release_short_version
,
:last_seen
,
:message
,
:project_id
,
:project_name
,
:project_slug
,
:short_id
,
:status
,
:title
,
:type
,
:user_count
end
end
app/serializers/error_tracking/detailed_error_serializer.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
DetailedErrorSerializer
<
BaseSerializer
entity
DetailedErrorEntity
end
end
app/serializers/error_tracking/error_event_entity.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
ErrorEventEntity
<
Grape
::
Entity
expose
:issue_id
,
:date_received
,
:stack_trace_entries
end
end
app/serializers/error_tracking/error_event_serializer.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
ErrorEventSerializer
<
BaseSerializer
entity
ErrorEventEntity
end
end
app/services/error_tracking/base_service.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
BaseService
<
::
BaseService
def
execute
unauthorized
=
check_permissions
return
unauthorized
if
unauthorized
begin
response
=
fetch
rescue
Sentry
::
Client
::
Error
=>
e
return
error
(
e
.
message
,
:bad_request
)
rescue
Sentry
::
Client
::
MissingKeysError
=>
e
return
error
(
e
.
message
,
:internal_server_error
)
end
errors
=
parse_errors
(
response
)
return
errors
if
errors
success
(
parse_response
(
response
))
end
private
def
fetch
raise
NotImplementedError
,
"
#{
self
.
class
}
does not implement
#{
__method__
}
"
end
def
parse_response
(
response
)
raise
NotImplementedError
,
"
#{
self
.
class
}
does not implement
#{
__method__
}
"
end
def
check_permissions
return
error
(
'Error Tracking is not enabled'
)
unless
enabled?
return
error
(
'Access denied'
,
:unauthorized
)
unless
can_read?
end
def
parse_errors
(
response
)
return
error
(
'Not ready. Try again later'
,
:no_content
)
unless
response
return
error
(
response
[
:error
],
http_status_for
(
response
[
:error_type
]))
if
response
[
:error
].
present?
end
def
http_status_for
(
error_type
)
case
error_type
when
ErrorTracking
::
ProjectErrorTrackingSetting
::
SENTRY_API_ERROR_TYPE_MISSING_KEYS
:internal_server_error
else
:bad_request
end
end
def
project_error_tracking_setting
project
.
error_tracking_setting
end
def
enabled?
project_error_tracking_setting
&
.
enabled?
end
def
can_read?
can?
(
current_user
,
:read_sentry_issue
,
project
)
end
end
end
app/services/error_tracking/issue_details_service.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
IssueDetailsService
<
ErrorTracking
::
BaseService
private
def
fetch
project_error_tracking_setting
.
issue_details
(
issue_id:
params
[
:issue_id
])
end
def
parse_response
(
response
)
{
issue:
response
[
:issue
]
}
end
end
end
app/services/error_tracking/issue_latest_event_service.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
IssueLatestEventService
<
ErrorTracking
::
BaseService
private
def
fetch
project_error_tracking_setting
.
issue_latest_event
(
issue_id:
params
[
:issue_id
])
end
def
parse_response
(
response
)
{
latest_event:
response
[
:latest_event
]
}
end
end
end
app/services/error_tracking/list_issues_service.rb
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
ListIssuesService
<
::
BaseService
class
ListIssuesService
<
ErrorTracking
::
BaseService
DEFAULT_ISSUE_STATUS
=
'unresolved'
DEFAULT_LIMIT
=
20
def
execute
return
error
(
'Error Tracking is not enabled'
)
unless
enabled?
return
error
(
'Access denied'
,
:unauthorized
)
unless
can_read?
result
=
project_error_tracking_setting
.
list_sentry_issues
(
issue_status:
issue_status
,
limit:
limit
)
# our results are not yet ready
unless
result
return
error
(
'Not ready. Try again later'
,
:no_content
)
end
private
if
result
[
:error
].
present?
return
error
(
result
[
:error
],
http_status_from_error_type
(
result
[
:error_type
])
)
end
def
fetch
project_error_tracking_setting
.
list_sentry_issues
(
issue_status:
issue_status
,
limit:
limit
)
end
success
(
issues:
result
[
:issues
])
def
parse_response
(
response
)
{
issues:
response
[
:issues
]
}
end
def
external_url
project_error_tracking_setting
&
.
sentry_external_url
end
private
def
http_status_from_error_type
(
error_type
)
case
error_type
when
ErrorTracking
::
ProjectErrorTrackingSetting
::
SENTRY_API_ERROR_TYPE_MISSING_KEYS
:internal_server_error
else
:bad_request
end
end
def
project_error_tracking_setting
project
.
error_tracking_setting
end
def
issue_status
params
[
:issue_status
]
||
DEFAULT_ISSUE_STATUS
end
...
...
@@ -50,13 +26,5 @@ module ErrorTracking
def
limit
params
[
:limit
]
||
DEFAULT_LIMIT
end
def
enabled?
project_error_tracking_setting
&
.
enabled?
end
def
can_read?
can?
(
current_user
,
:read_sentry_issue
,
project
)
end
end
end
app/services/error_tracking/list_projects_service.rb
View file @
ae72d71d
# frozen_string_literal: true
module
ErrorTracking
class
ListProjectsService
<
::
BaseService
class
ListProjectsService
<
ErrorTracking
::
BaseService
def
execute
return
error
(
'access denied'
)
unless
can_read?
setting
=
project_error_tracking_setting
unless
setting
.
valid?
return
error
(
setting
.
errors
.
full_messages
.
join
(
', '
),
:bad_request
)
unless
project_error_tracking_setting
.
valid?
return
error
(
project_error_tracking_setting
.
errors
.
full_messages
.
join
(
', '
),
:bad_request
)
end
begin
result
=
setting
.
list_sentry_projects
rescue
Sentry
::
Client
::
Error
=>
e
return
error
(
e
.
message
,
:bad_request
)
rescue
Sentry
::
Client
::
MissingKeysError
=>
e
return
error
(
e
.
message
,
:internal_server_error
)
end
success
(
projects:
result
[
:projects
])
super
end
private
def
project_error_tracking_setting
(
project
.
error_tracking_setting
||
project
.
build_error_tracking_setting
).
tap
do
|
setting
|
setting
.
api_url
=
ErrorTracking
::
ProjectErrorTrackingSetting
.
build_api_url_from
(
api_host:
params
[
:api_host
],
organization_slug:
'org'
,
project_slug:
'proj'
)
setting
.
token
=
token
(
setting
)
setting
.
enabled
=
true
end
def
fetch
project_error_tracking_setting
.
list_sentry_projects
end
def
parse_response
(
response
)
{
projects:
response
[
:projects
]
}
end
def
can_read?
can?
(
current_user
,
:read_sentry_issue
,
project
)
def
project_error_tracking_setting
@project_error_tracking_setting
||=
begin
(
super
||
project
.
build_error_tracking_setting
).
tap
do
|
setting
|
setting
.
api_url
=
ErrorTracking
::
ProjectErrorTrackingSetting
.
build_api_url_from
(
api_host:
params
[
:api_host
],
organization_slug:
'org'
,
project_slug:
'proj'
)
setting
.
token
=
token
(
setting
)
setting
.
enabled
=
true
end
end
end
def
token
(
setting
)
...
...
app/views/admin/application_settings/_snowplow.html.haml
View file @
ae72d71d
...
...
@@ -21,8 +21,8 @@
=
f
.
label
:snowplow_collector_hostname
,
_
(
'Collector hostname'
),
class:
'label-light'
=
f
.
text_field
:snowplow_collector_hostname
,
class:
'form-control'
,
placeholder:
'snowplow.example.com'
.form-group
=
f
.
label
:snowplow_
site_id
,
_
(
'Site
ID'
),
class:
'label-light'
=
f
.
text_field
:snowplow_
site
_id
,
class:
'form-control'
=
f
.
label
:snowplow_
app_id
,
_
(
'App
ID'
),
class:
'label-light'
=
f
.
text_field
:snowplow_
app
_id
,
class:
'form-control'
.form-group
=
f
.
label
:snowplow_cookie_domain
,
_
(
'Cookie domain'
),
class:
'label-light'
=
f
.
text_field
:snowplow_cookie_domain
,
class:
'form-control'
...
...
app/views/layouts/nav/sidebar/_project.html.haml
View file @
ae72d71d
...
...
@@ -247,6 +247,8 @@
%span
=
_
(
'Serverless'
)
=
render_if_exists
'layouts/nav/sidebar/pod_logs_link'
# EE-specific
-
if
project_nav_tab?
:clusters
-
show_cluster_hint
=
show_gke_cluster_integration_callout?
(
@project
)
=
nav_link
(
controller:
[
:clusters
,
:user
,
:gcp
])
do
...
...
app/views/projects/environments/empty_logs.html.haml
0 → 100644
View file @
ae72d71d
-
page_title
_
(
'Pod logs'
)
.row.empty-state
.col-sm-12
.svg-content
=
image_tag
'illustrations/operations_log_pods_empty.svg'
.col-12
.text-content
%h4
.text-center
=
s_
(
'Environments|No deployed environments'
)
%p
.state-description.text-center
=
s_
(
'Logs|To see the pod logs, deploy your code to an environment.'
)
.text-center
=
link_to
s_
(
'Environments|Learn about environments'
),
help_page_path
(
'ci/environments'
),
class:
'btn btn-success'
app/views/projects/environments/empty.html.haml
→
app/views/projects/environments/empty
_metrics
.html.haml
View file @
ae72d71d
...
...
@@ -7,8 +7,8 @@
.col-12
.text-content
%h4
.text-center
=
s_
(
'
Metric
s|No deployed environments'
)
=
s_
(
'
Environment
s|No deployed environments'
)
%p
.state-description
=
s_
(
'Metrics|Check out the CI/CD documentation on deploying to an environment'
)
.text-center
=
link_to
s_
(
"
Metric
s|Learn about environments"
),
help_page_path
(
'ci/environments'
),
class:
'btn btn-success'
=
link_to
s_
(
"
Environment
s|Learn about environments"
),
help_page_path
(
'ci/environments'
),
class:
'btn btn-success'
app/views/projects/error_tracking/details.html.haml
0 → 100644
View file @
ae72d71d
-
page_title
_
(
'Error Details'
)
#js-error_tracking
{
data:
error_details_data
(
@current_user
,
@project
)
}
changelogs/unreleased/31222-follow-up-from-adjusts-snowplow-to-use-cookies-for-sessions.yml
0 → 100644
View file @
ae72d71d
---
title
:
Rename snowplow_site_id to snowplow_app_id in application_settings table
merge_request
:
19252
author
:
type
:
other
changelogs/unreleased/32052-add-pa-start-date-limit.yml
0 → 100644
View file @
ae72d71d
---
title
:
Add productivity analytics merge date filtering limit
merge_request
:
32052
author
:
type
:
fixed
changelogs/unreleased/32464-backend-sentry-error-details.yml
0 → 100644
View file @
ae72d71d
---
title
:
API for stack trace & detail view of Sentry error in GitLab
merge_request
:
19137
author
:
type
:
added
config/routes/project.rb
View file @
ae72d71d
...
...
@@ -441,6 +441,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get
:metrics
,
action: :metrics_redirect
get
:folder
,
path:
'folders/*id'
,
constraints:
{
format:
/(html|json)/
}
get
:search
Gitlab
.
ee
do
get
:logs
,
action: :logs_redirect
end
end
resources
:deployments
,
only:
[
:index
]
do
...
...
@@ -613,6 +617,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources
:error_tracking
,
only:
[
:index
],
controller: :error_tracking
do
collection
do
get
':issue_id/details'
,
to:
'error_tracking#details'
,
as:
'details'
get
':issue_id/stack_trace'
,
to:
'error_tracking#stack_trace'
,
as:
'stack_trace'
post
:list_projects
end
end
...
...
db/migrate/20191004080818_add_productivity_analytics_start_date.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
class
AddProductivityAnalyticsStartDate
<
ActiveRecord
::
Migration
[
5.2
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
def
change
add_column
:application_settings
,
:productivity_analytics_start_date
,
:datetime_with_timezone
end
end
db/migrate/20191004081520_fill_productivity_analytics_start_date.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
# Expected migration duration: 1 minute
class
FillProductivityAnalyticsStartDate
<
ActiveRecord
::
Migration
[
5.2
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
add_concurrent_index
:merge_request_metrics
,
:merged_at
,
where:
"merged_at > '2019-09-01' AND commits_count IS NOT NULL"
,
name:
'fill_productivity_analytics_start_date_tmp_index'
execute
(
<<
SQL
UPDATE application_settings
SET productivity_analytics_start_date = COALESCE((SELECT MIN(merged_at) FROM merge_request_metrics
WHERE merged_at > '2019-09-01' AND commits_count IS NOT NULL), NOW())
SQL
)
remove_concurrent_index
:merge_request_metrics
,
:merged_at
,
name:
'fill_productivity_analytics_start_date_tmp_index'
end
def
down
execute
(
'UPDATE application_settings SET productivity_analytics_start_date = NULL'
)
end
end
db/migrate/20191028184740_rename_snowplow_site_id_to_snowplow_app_id.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
class
RenameSnowplowSiteIdToSnowplowAppId
<
ActiveRecord
::
Migration
[
5.2
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
rename_column_concurrently
:application_settings
,
:snowplow_site_id
,
:snowplow_app_id
end
def
down
undo_rename_column_concurrently
:application_settings
,
:snowplow_site_id
,
:snowplow_app_id
end
end
db/post_migrate/20191029095537_cleanup_application_settings_snowplow_site_id_rename.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
class
CleanupApplicationSettingsSnowplowSiteIdRename
<
ActiveRecord
::
Migration
[
5.2
]
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
cleanup_concurrent_column_rename
:application_settings
,
:snowplow_site_id
,
:snowplow_app_id
end
def
down
undo_cleanup_concurrent_column_rename
:application_settings
,
:snowplow_site_id
,
:snowplow_app_id
end
end
db/schema.rb
View file @
ae72d71d
...
...
@@ -287,7 +287,6 @@ ActiveRecord::Schema.define(version: 2019_11_05_094625) do
t
.
boolean
"hide_third_party_offers"
,
default:
false
,
null:
false
t
.
boolean
"snowplow_enabled"
,
default:
false
,
null:
false
t
.
string
"snowplow_collector_hostname"
t
.
string
"snowplow_site_id"
t
.
string
"snowplow_cookie_domain"
t
.
boolean
"instance_statistics_visibility_private"
,
default:
false
,
null:
false
t
.
boolean
"web_ide_clientside_preview_enabled"
,
default:
false
,
null:
false
...
...
@@ -350,6 +349,8 @@ ActiveRecord::Schema.define(version: 2019_11_05_094625) do
t
.
string
"eks_access_key_id"
,
limit:
128
t
.
string
"encrypted_eks_secret_access_key_iv"
,
limit:
255
t
.
text
"encrypted_eks_secret_access_key"
t
.
string
"snowplow_app_id"
t
.
datetime_with_timezone
"productivity_analytics_start_date"
t
.
index
[
"custom_project_templates_group_id"
],
name:
"index_application_settings_on_custom_project_templates_group_id"
t
.
index
[
"file_template_project_id"
],
name:
"index_application_settings_on_file_template_project_id"
t
.
index
[
"instance_administration_project_id"
],
name:
"index_applicationsettings_on_instance_administration_project_id"
...
...
doc/api/settings.md
View file @
ae72d71d
...
...
@@ -319,7 +319,7 @@ are listed in the descriptions of the relevant settings.
|
`snowplow_collector_hostname`
| string | required by:
`snowplow_enabled`
| The Snowplow collector hostname. (e.g.
`snowplow.trx.gitlab.net`
) |
|
`snowplow_cookie_domain`
| string | no | The Snowplow cookie domain. (e.g.
`.gitlab.com`
) |
|
`snowplow_enabled`
| boolean | no | Enable snowplow tracking. |
|
`snowplow_
site_id`
| string | no | The Snowplow site name / application id. (e.g.
`gitlab`
) |
|
`snowplow_
app_id`
| string | no | The Snowplow site name / application id. (e.g.
`gitlab`
) |
|
`snowplow_iglu_registry_url`
| string | no | The Snowplow base Iglu Schema Registry URL to use for custom context and self describing events'|
|
`pendo_url`
| string | required by:
`pendo_enabled`
| The Pendo endpoint url with js snippet. (e.g.
`https://cdn.pendo.io/agent/static/your-api-key/pendo.js`
) |
|
`pendo_enabled`
| boolean | no | Enable pendo tracking. |
...
...
doc/ci/yaml/README.md
View file @
ae72d71d
...
...
@@ -135,6 +135,7 @@ The following job parameters can be defined inside a `default:` block:
-
[
`before_script`
](
#before_script-and-after_script
)
-
[
`after_script`
](
#before_script-and-after_script
)
-
[
`cache`
](
#cache
)
-
[
`interruptible`
](
#interruptible
)
In the following example, the
`ruby:2.5`
image is set as the default for all
jobs except the
`rspec 2.6`
job, which uses the
`ruby:2.6`
image:
...
...
lib/api/merge_requests.rb
View file @
ae72d71d
...
...
@@ -296,9 +296,12 @@ module API
end
get
':id/merge_requests/:merge_request_iid/commits'
do
merge_request
=
find_merge_request_with_access
(
params
[
:merge_request_iid
])
commits
=
::
Kaminari
.
paginate_array
(
merge_request
.
commits
)
present
paginate
(
commits
),
with:
Entities
::
Commit
commits
=
paginate
(
merge_request
.
merge_request_diff
.
merge_request_diff_commits
)
.
map
{
|
commit
|
Commit
.
from_hash
(
commit
.
to_hash
,
merge_request
.
project
)
}
present
commits
,
with:
Entities
::
Commit
end
desc
'Show the merge request changes'
do
...
...
lib/api/settings.rb
View file @
ae72d71d
...
...
@@ -145,7 +145,7 @@ module API
given
snowplow_enabled:
->
(
val
)
{
val
}
do
requires
:snowplow_collector_hostname
,
type:
String
,
desc:
'The Snowplow collector hostname'
optional
:snowplow_cookie_domain
,
type:
String
,
desc:
'The Snowplow cookie domain'
optional
:snowplow_
site_id
,
type:
String
,
desc:
'The Snowplow site name / application ic
'
optional
:snowplow_
app_id
,
type:
String
,
desc:
'The Snowplow site name / application id
'
end
optional
:pendo_enabled
,
type:
Grape
::
API
::
Boolean
,
desc:
'Enable Pendo tracking'
given
pendo_enabled:
->
(
val
)
{
val
}
do
...
...
lib/gitlab/ci/config/entry/boolean.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
Gitlab
module
Ci
class
Config
module
Entry
##
# Entry that represents the interrutible value.
#
class
Boolean
<
::
Gitlab
::
Config
::
Entry
::
Node
include
::
Gitlab
::
Config
::
Entry
::
Validatable
validations
do
validates
:config
,
boolean:
true
end
end
end
end
end
end
lib/gitlab/ci/config/entry/default.rb
View file @
ae72d71d
...
...
@@ -14,7 +14,7 @@ module Gitlab
include
::
Gitlab
::
Config
::
Entry
::
Inheritable
ALLOWED_KEYS
=
%i[before_script image services
after_script cache]
.
freeze
after_script cache
interruptible
]
.
freeze
validations
do
validates
:config
,
allowed_keys:
ALLOWED_KEYS
...
...
@@ -40,7 +40,11 @@ module Gitlab
description:
'Configure caching between build jobs.'
,
inherit:
true
helpers
:before_script
,
:image
,
:services
,
:after_script
,
:cache
entry
:interruptible
,
Entry
::
Boolean
,
description:
'Set jobs interruptible default value.'
,
inherit:
false
helpers
:before_script
,
:image
,
:services
,
:after_script
,
:cache
,
:interruptible
private
...
...
lib/gitlab/ci/config/entry/job.rb
View file @
ae72d71d
...
...
@@ -38,7 +38,6 @@ module Gitlab
with_options
allow_nil:
true
do
validates
:tags
,
array_of_strings:
true
validates
:allow_failure
,
boolean:
true
validates
:interruptible
,
boolean:
true
validates
:parallel
,
numericality:
{
only_integer:
true
,
greater_than_or_equal_to:
2
,
less_than_or_equal_to:
50
}
...
...
@@ -100,6 +99,10 @@ module Gitlab
description:
'Services that will be used to execute this job.'
,
inherit:
true
entry
:interruptible
,
Entry
::
Boolean
,
description:
'Set jobs interruptible value.'
,
inherit:
true
entry
:only
,
Entry
::
Policy
,
description:
'Refs policy this job will be executed for.'
,
default:
Entry
::
Policy
::
DEFAULT_ONLY
,
...
...
lib/gitlab/error_tracking/detailed_error.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
Gitlab
module
ErrorTracking
class
DetailedError
include
ActiveModel
::
Model
attr_accessor
:count
,
:culprit
,
:external_base_url
,
:external_url
,
:first_release_last_commit
,
:first_release_short_version
,
:first_seen
,
:frequency
,
:id
,
:last_release_last_commit
,
:last_release_short_version
,
:last_seen
,
:message
,
:project_id
,
:project_name
,
:project_slug
,
:short_id
,
:status
,
:title
,
:type
,
:user_count
end
end
end
lib/gitlab/error_tracking/error_event.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
module
Gitlab
module
ErrorTracking
class
ErrorEvent
include
ActiveModel
::
Model
attr_accessor
:issue_id
,
:date_received
,
:stack_trace_entries
end
end
end
lib/gitlab/tracking.rb
View file @
ae72d71d
...
...
@@ -45,7 +45,7 @@ module Gitlab
namespace:
SNOWPLOW_NAMESPACE
,
hostname:
Gitlab
::
CurrentSettings
.
snowplow_collector_hostname
,
cookie_domain:
Gitlab
::
CurrentSettings
.
snowplow_cookie_domain
,
app_id:
Gitlab
::
CurrentSettings
.
snowplow_
site
_id
,
app_id:
Gitlab
::
CurrentSettings
.
snowplow_
app
_id
,
form_tracking:
additional_features
,
link_click_tracking:
additional_features
,
iglu_registry_url:
Gitlab
::
CurrentSettings
.
snowplow_iglu_registry_url
...
...
@@ -59,7 +59,7 @@ module Gitlab
SnowplowTracker
::
AsyncEmitter
.
new
(
Gitlab
::
CurrentSettings
.
snowplow_collector_hostname
,
protocol:
'https'
),
SnowplowTracker
::
Subject
.
new
,
SNOWPLOW_NAMESPACE
,
Gitlab
::
CurrentSettings
.
snowplow_
site
_id
Gitlab
::
CurrentSettings
.
snowplow_
app
_id
)
end
end
...
...
lib/sentry/client.rb
View file @
ae72d71d
...
...
@@ -12,6 +12,18 @@ module Sentry
@token
=
token
end
def
issue_details
(
issue_id
:)
issue
=
get_issue
(
issue_id:
issue_id
)
map_to_detailed_error
(
issue
)
end
def
issue_latest_event
(
issue_id
:)
latest_event
=
get_issue_latest_event
(
issue_id:
issue_id
)
map_to_event
(
latest_event
)
end
def
list_issues
(
issue_status
:,
limit
:)
issues
=
get_issues
(
issue_status:
issue_status
,
limit:
limit
)
...
...
@@ -61,6 +73,14 @@ module Sentry
})
end
def
get_issue
(
issue_id
:)
http_get
(
issue_api_url
(
issue_id
))
end
def
get_issue_latest_event
(
issue_id
:)
http_get
(
issue_latest_event_api_url
(
issue_id
))
end
def
get_projects
http_get
(
projects_api_url
)
end
...
...
@@ -102,6 +122,20 @@ module Sentry
projects_url
end
def
issue_api_url
(
issue_id
)
issue_url
=
URI
(
@url
)
issue_url
.
path
=
"/api/0/issues/
#{
issue_id
}
/"
issue_url
end
def
issue_latest_event_api_url
(
issue_id
)
latest_event_url
=
URI
(
@url
)
latest_event_url
.
path
=
"/api/0/issues/
#{
issue_id
}
/events/latest/"
latest_event_url
end
def
issues_api_url
issues_url
=
URI
(
@url
+
'/issues/'
)
issues_url
.
path
.
squeeze!
(
'/'
)
...
...
@@ -119,38 +153,87 @@ module Sentry
def
issue_url
(
id
)
issues_url
=
@url
+
"/issues/
#{
id
}
"
issues_url
=
ErrorTracking
::
ProjectErrorTrackingSetting
.
extract_sentry_external_url
(
issues_url
)
uri
=
URI
(
issues_url
)
parse_sentry_url
(
issues_url
)
end
def
project_url
parse_sentry_url
(
@url
)
end
def
parse_sentry_url
(
api_url
)
url
=
ErrorTracking
::
ProjectErrorTrackingSetting
.
extract_sentry_external_url
(
api_url
)
uri
=
URI
(
url
)
uri
.
path
.
squeeze!
(
'/'
)
# Remove trailing spaces
uri
=
uri
.
to_s
.
gsub
(
/\/\z/
,
''
)
uri
.
to_s
uri
end
def
map_to_error
(
issue
)
id
=
issue
.
fetch
(
'id'
)
def
map_to_event
(
event
)
stack_trace
=
parse_stack_trace
(
event
)
Gitlab
::
ErrorTracking
::
ErrorEvent
.
new
(
issue_id:
event
.
dig
(
'groupID'
),
date_received:
event
.
dig
(
'dateReceived'
),
stack_trace_entries:
stack_trace
)
end
count
=
issue
.
fetch
(
'count'
,
nil
)
def
parse_stack_trace
(
event
)
exception_entry
=
event
.
dig
(
'entries'
)
&
.
detect
{
|
h
|
h
[
'type'
]
==
'exception'
}
return
unless
exception_entry
frequency
=
issue
.
dig
(
'stats'
,
'24h'
)
message
=
issue
.
dig
(
'metadata'
,
'value'
)
exception_values
=
exception_entry
.
dig
(
'data'
,
'values'
)
stack_trace_entry
=
exception_values
&
.
detect
{
|
h
|
h
[
'stacktrace'
].
present?
}
return
unless
stack_trace_entry
external_url
=
issue_url
(
id
)
stack_trace_entry
.
dig
(
'stacktrace'
,
'frames'
)
end
def
map_to_detailed_error
(
issue
)
Gitlab
::
ErrorTracking
::
DetailedError
.
new
(
id:
issue
.
fetch
(
'id'
),
first_seen:
issue
.
fetch
(
'firstSeen'
,
nil
),
last_seen:
issue
.
fetch
(
'lastSeen'
,
nil
),
title:
issue
.
fetch
(
'title'
,
nil
),
type:
issue
.
fetch
(
'type'
,
nil
),
user_count:
issue
.
fetch
(
'userCount'
,
nil
),
count:
issue
.
fetch
(
'count'
,
nil
),
message:
issue
.
dig
(
'metadata'
,
'value'
),
culprit:
issue
.
fetch
(
'culprit'
,
nil
),
external_url:
issue_url
(
issue
.
fetch
(
'id'
)),
external_base_url:
project_url
,
short_id:
issue
.
fetch
(
'shortId'
,
nil
),
status:
issue
.
fetch
(
'status'
,
nil
),
frequency:
issue
.
dig
(
'stats'
,
'24h'
),
project_id:
issue
.
dig
(
'project'
,
'id'
),
project_name:
issue
.
dig
(
'project'
,
'name'
),
project_slug:
issue
.
dig
(
'project'
,
'slug'
),
first_release_last_commit:
issue
.
dig
(
'firstRelease'
,
'lastCommit'
),
last_release_last_commit:
issue
.
dig
(
'lastRelease'
,
'lastCommit'
),
first_release_short_version:
issue
.
dig
(
'firstRelease'
,
'shortVersion'
),
last_release_short_version:
issue
.
dig
(
'lastRelease'
,
'shortVersion'
)
)
end
def
map_to_error
(
issue
)
Gitlab
::
ErrorTracking
::
Error
.
new
(
id:
i
d
,
id:
i
ssue
.
fetch
(
'id'
)
,
first_seen:
issue
.
fetch
(
'firstSeen'
,
nil
),
last_seen:
issue
.
fetch
(
'lastSeen'
,
nil
),
title:
issue
.
fetch
(
'title'
,
nil
),
type:
issue
.
fetch
(
'type'
,
nil
),
user_count:
issue
.
fetch
(
'userCount'
,
nil
),
count:
count
,
message:
message
,
count:
issue
.
fetch
(
'count'
,
nil
)
,
message:
issue
.
dig
(
'metadata'
,
'value'
)
,
culprit:
issue
.
fetch
(
'culprit'
,
nil
),
external_url:
external_url
,
external_url:
issue_url
(
issue
.
fetch
(
'id'
))
,
short_id:
issue
.
fetch
(
'shortId'
,
nil
),
status:
issue
.
fetch
(
'status'
,
nil
),
frequency:
frequency
,
frequency:
issue
.
dig
(
'stats'
,
'24h'
)
,
project_id:
issue
.
dig
(
'project'
,
'id'
),
project_name:
issue
.
dig
(
'project'
,
'name'
),
project_slug:
issue
.
dig
(
'project'
,
'slug'
)
...
...
locale/gitlab.pot
View file @
ae72d71d
...
...
@@ -1798,6 +1798,9 @@ msgstr ""
msgid "Any user"
msgstr ""
msgid "App ID"
msgstr ""
msgid "Appearance"
msgstr ""
...
...
@@ -6406,12 +6409,18 @@ msgstr ""
msgid "Environments|Job"
msgstr ""
msgid "Environments|Learn about environments"
msgstr ""
msgid "Environments|Learn more about stopping environments"
msgstr ""
msgid "Environments|New environment"
msgstr ""
msgid "Environments|No deployed environments"
msgstr ""
msgid "Environments|No deployments yet"
msgstr ""
...
...
@@ -6580,6 +6589,9 @@ msgstr ""
msgid "Error"
msgstr ""
msgid "Error Details"
msgstr ""
msgid "Error Tracking"
msgstr ""
...
...
@@ -10177,6 +10189,9 @@ msgstr ""
msgid "Logs"
msgstr ""
msgid "Logs|To see the pod logs, deploy your code to an environment."
msgstr ""
msgid "MD5"
msgstr ""
...
...
@@ -10678,9 +10693,6 @@ msgstr ""
msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
msgstr ""
msgid "Metrics|Learn about environments"
msgstr ""
msgid "Metrics|Legend label (optional)"
msgstr ""
...
...
@@ -10696,9 +10708,6 @@ msgstr ""
msgid "Metrics|New metric"
msgstr ""
msgid "Metrics|No deployed environments"
msgstr ""
msgid "Metrics|PromQL query is valid"
msgstr ""
...
...
@@ -12355,6 +12364,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
msgid "Pod logs"
msgstr ""
msgid "Pod not found"
msgstr ""
...
...
@@ -15599,9 +15611,6 @@ msgstr ""
msgid "Single or combined queries"
msgstr ""
msgid "Site ID"
msgstr ""
msgid "Size"
msgstr ""
...
...
spec/controllers/application_controller_spec.rb
View file @
ae72d71d
...
...
@@ -90,14 +90,6 @@ describe ApplicationController do
let
(
:format
)
{
:html
}
it_behaves_like
'setting gon variables'
context
'for peek requests'
do
before
do
request
.
path
=
'/-/peek'
end
it_behaves_like
'not setting gon variables'
end
end
context
'with json format'
do
...
...
@@ -105,6 +97,12 @@ describe ApplicationController do
it_behaves_like
'not setting gon variables'
end
context
'with atom format'
do
let
(
:format
)
{
:atom
}
it_behaves_like
'not setting gon variables'
end
end
describe
'session expiration'
do
...
...
spec/controllers/projects/environments_controller_spec.rb
View file @
ae72d71d
...
...
@@ -330,11 +330,11 @@ describe Projects::EnvironmentsController do
expect
(
response
).
to
redirect_to
(
environment_metrics_path
(
environment
))
end
it
'redirects to empty page if no environment exists'
do
it
'redirects to empty
metrics
page if no environment exists'
do
get
:metrics_redirect
,
params:
{
namespace_id:
project
.
namespace
,
project_id:
project
}
expect
(
response
).
to
be_ok
expect
(
response
).
to
render_template
'empty'
expect
(
response
).
to
render_template
'empty
_metrics
'
end
end
...
...
spec/controllers/projects/error_tracking_controller_spec.rb
View file @
ae72d71d
...
...
@@ -46,17 +46,6 @@ describe Projects::ErrorTrackingController do
end
describe
'format json'
do
shared_examples
'no data'
do
it
'returns no data'
do
get
:index
,
params:
project_params
(
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'error_tracking/index'
)
expect
(
json_response
[
'external_url'
]).
to
be_nil
expect
(
json_response
[
'errors'
]).
to
eq
([])
end
end
let
(
:list_issues_service
)
{
spy
(
:list_issues_service
)
}
let
(
:external_url
)
{
'http://example.com'
}
...
...
@@ -66,6 +55,19 @@ describe Projects::ErrorTrackingController do
.
and_return
(
list_issues_service
)
end
context
'no data'
do
before
do
expect
(
list_issues_service
).
to
receive
(
:execute
)
.
and_return
(
status: :error
,
http_status: :no_content
)
end
it
'returns no data'
do
get
:index
,
params:
project_params
(
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:no_content
)
end
end
context
'service result is successful'
do
before
do
expect
(
list_issues_service
).
to
receive
(
:execute
)
...
...
@@ -232,8 +234,186 @@ describe Projects::ErrorTrackingController do
end
end
describe
'GET #issue_details'
do
let_it_be
(
:issue_id
)
{
1234
}
let
(
:issue_details_service
)
{
spy
(
:issue_details_service
)
}
let
(
:permitted_params
)
do
ActionController
::
Parameters
.
new
(
{
issue_id:
issue_id
.
to_s
}
).
permit!
end
before
do
expect
(
ErrorTracking
::
IssueDetailsService
)
.
to
receive
(
:new
).
with
(
project
,
user
,
permitted_params
)
.
and_return
(
issue_details_service
)
end
describe
'format json'
do
context
'no data'
do
before
do
expect
(
issue_details_service
).
to
receive
(
:execute
)
.
and_return
(
status: :error
,
http_status: :no_content
)
end
it
'returns no data'
do
get
:details
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:no_content
)
end
end
context
'service result is successful'
do
before
do
expect
(
issue_details_service
).
to
receive
(
:execute
)
.
and_return
(
status: :success
,
issue:
error
)
end
let
(
:error
)
{
build
(
:detailed_error_tracking_error
)
}
it
'returns an error'
do
get
:details
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'error_tracking/issue_detailed'
)
expect
(
json_response
[
'error'
]).
to
eq
(
error
.
as_json
)
end
end
context
'service result is erroneous'
do
let
(
:error_message
)
{
'error message'
}
context
'without http_status'
do
before
do
expect
(
issue_details_service
).
to
receive
(
:execute
)
.
and_return
(
status: :error
,
message:
error_message
)
end
it
'returns 400 with message'
do
get
:details
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:bad_request
)
expect
(
json_response
[
'message'
]).
to
eq
(
error_message
)
end
end
context
'with explicit http_status'
do
let
(
:http_status
)
{
:no_content
}
before
do
expect
(
issue_details_service
).
to
receive
(
:execute
).
and_return
(
status: :error
,
message:
error_message
,
http_status:
http_status
)
end
it
'returns http_status with message'
do
get
:details
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
http_status
)
expect
(
json_response
[
'message'
]).
to
eq
(
error_message
)
end
end
end
end
end
describe
'GET #stack_trace'
do
let_it_be
(
:issue_id
)
{
1234
}
let
(
:issue_stack_trace_service
)
{
spy
(
:issue_stack_trace_service
)
}
let
(
:permitted_params
)
do
ActionController
::
Parameters
.
new
(
{
issue_id:
issue_id
.
to_s
}
).
permit!
end
before
do
expect
(
ErrorTracking
::
IssueLatestEventService
)
.
to
receive
(
:new
).
with
(
project
,
user
,
permitted_params
)
.
and_return
(
issue_stack_trace_service
)
end
describe
'format json'
do
context
'awaiting data'
do
before
do
expect
(
issue_stack_trace_service
).
to
receive
(
:execute
)
.
and_return
(
status: :error
,
http_status: :no_content
)
end
it
'returns no data'
do
get
:stack_trace
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:no_content
)
end
end
context
'service result is successful'
do
before
do
expect
(
issue_stack_trace_service
).
to
receive
(
:execute
)
.
and_return
(
status: :success
,
latest_event:
error_event
)
end
let
(
:error_event
)
{
build
(
:error_tracking_error_event
)
}
it
'returns an error'
do
get
:stack_trace
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
match_response_schema
(
'error_tracking/issue_stack_trace'
)
expect
(
json_response
[
'error'
]).
to
eq
(
error_event
.
as_json
)
end
end
context
'service result is erroneous'
do
let
(
:error_message
)
{
'error message'
}
context
'without http_status'
do
before
do
expect
(
issue_stack_trace_service
).
to
receive
(
:execute
)
.
and_return
(
status: :error
,
message:
error_message
)
end
it
'returns 400 with message'
do
get
:stack_trace
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:bad_request
)
expect
(
json_response
[
'message'
]).
to
eq
(
error_message
)
end
end
context
'with explicit http_status'
do
let
(
:http_status
)
{
:no_content
}
before
do
expect
(
issue_stack_trace_service
).
to
receive
(
:execute
).
and_return
(
status: :error
,
message:
error_message
,
http_status:
http_status
)
end
it
'returns http_status with message'
do
get
:stack_trace
,
params:
issue_params
(
issue_id:
issue_id
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
http_status
)
expect
(
json_response
[
'message'
]).
to
eq
(
error_message
)
end
end
end
end
end
private
def
issue_params
(
opts
=
{})
project_params
.
reverse_merge
(
opts
)
end
def
project_params
(
opts
=
{})
opts
.
reverse_merge
(
namespace_id:
project
.
namespace
,
project_id:
project
)
end
...
...
spec/controllers/uploads_controller_spec.rb
View file @
ae72d71d
...
...
@@ -228,10 +228,10 @@ describe UploadsController do
user
.
block
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"user"
,
mounted_as:
"avatar"
,
id:
user
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -320,10 +320,10 @@ describe UploadsController do
end
context
"when not signed in"
do
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"project"
,
mounted_as:
"avatar"
,
id:
project
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -343,10 +343,10 @@ describe UploadsController do
project
.
add_maintainer
(
user
)
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"project"
,
mounted_as:
"avatar"
,
id:
project
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -439,10 +439,10 @@ describe UploadsController do
user
.
block
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"group"
,
mounted_as:
"avatar"
,
id:
group
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -526,10 +526,10 @@ describe UploadsController do
end
context
"when not signed in"
do
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"note"
,
mounted_as:
"attachment"
,
id:
note
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
@@ -549,10 +549,10 @@ describe UploadsController do
project
.
add_maintainer
(
user
)
end
it
"re
directs to the sign in page
"
do
it
"re
sponds with status 401
"
do
get
:show
,
params:
{
model:
"note"
,
mounted_as:
"attachment"
,
id:
note
.
id
,
filename:
"dk.png"
}
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
expect
(
response
).
to
have_gitlab_http_status
(
401
)
end
end
...
...
spec/db/schema_spec.rb
View file @
ae72d71d
...
...
@@ -13,7 +13,7 @@ describe 'Database schema' do
# EE: edit the ee/spec/db/schema_support.rb
IGNORED_FK_COLUMNS
=
{
abuse_reports:
%w[reporter_id user_id]
,
application_settings:
%w[performance_bar_allowed_group_id slack_app_id snowplow_
site
_id eks_account_id eks_access_key_id]
,
application_settings:
%w[performance_bar_allowed_group_id slack_app_id snowplow_
app
_id eks_account_id eks_access_key_id]
,
approvers:
%w[target_id user_id]
,
approvals:
%w[user_id]
,
approver_groups:
%w[target_id]
,
...
...
spec/factories/error_tracking/detailed_error.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
FactoryBot
.
define
do
factory
:detailed_error_tracking_error
,
class:
Gitlab
::
ErrorTracking
::
DetailedError
do
id
{
'id'
}
title
{
'title'
}
type
{
'error'
}
user_count
{
1
}
count
{
2
}
first_seen
{
Time
.
now
}
last_seen
{
Time
.
now
}
message
{
'message'
}
culprit
{
'culprit'
}
external_url
{
'http://example.com/id'
}
external_base_url
{
'http://example.com'
}
project_id
{
'project1'
}
project_name
{
'project name'
}
project_slug
{
'project_name'
}
short_id
{
'ID'
}
status
{
'unresolved'
}
frequency
{
[]
}
first_release_last_commit
{
'68c914da9'
}
last_release_last_commit
{
'9ad419c86'
}
first_release_short_version
{
'abc123'
}
last_release_short_version
{
'abc123'
}
skip_create
end
end
spec/factories/error_tracking/error_event.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
FactoryBot
.
define
do
factory
:error_tracking_error_event
,
class:
Gitlab
::
ErrorTracking
::
ErrorEvent
do
issue_id
{
'id'
}
date_received
{
Time
.
now
.
iso8601
}
stack_trace_entries
do
{
'stacktrace'
=>
{
'frames'
=>
[{
'file'
=>
'test.rb'
}]
}
}
end
skip_create
end
end
spec/features/projects/members/member_leaves_project_spec.rb
View file @
ae72d71d
...
...
@@ -20,7 +20,7 @@ describe 'Projects > Members > Member leaves project' do
expect
(
project
.
users
.
exists?
(
user
.
id
)).
to
be_falsey
end
it
'user leaves project by url param'
,
:js
do
it
'user leaves project by url param'
,
:js
,
:quarantine
do
visit
project_path
(
project
,
leave:
1
)
page
.
accept_confirm
...
...
spec/fixtures/api/schemas/error_tracking/error.json
View file @
ae72d71d
...
...
@@ -4,7 +4,14 @@
"external_url"
,
"last_seen"
,
"message"
,
"type"
"type"
,
"title"
,
"project_id"
,
"project_name"
,
"project_slug"
,
"short_id"
,
"status"
,
"frequency"
],
"properties"
:
{
"id"
:
{
"type"
:
"string"
},
...
...
@@ -15,7 +22,14 @@
"culprit"
:
{
"type"
:
"string"
},
"count"
:
{
"type"
:
"integer"
},
"external_url"
:
{
"type"
:
"string"
},
"user_count"
:
{
"type"
:
"integer"
}
"user_count"
:
{
"type"
:
"integer"
},
"title"
:
{
"type"
:
"string"
},
"project_id"
:
{
"type"
:
"string"
},
"project_name"
:
{
"type"
:
"string"
},
"project_slug"
:
{
"type"
:
"string"
},
"short_id"
:
{
"type"
:
"string"
},
"status"
:
{
"type"
:
"string"
},
"frequency"
:
{
"type"
:
"array"
}
},
"additionalProperties"
:
tru
e
"additionalProperties"
:
fals
e
}
spec/fixtures/api/schemas/error_tracking/error_detailed.json
0 → 100644
View file @
ae72d71d
{
"type"
:
"object"
,
"required"
:
[
"external_url"
,
"external_base_url"
,
"last_seen"
,
"message"
,
"type"
,
"title"
,
"project_id"
,
"project_name"
,
"project_slug"
,
"short_id"
,
"status"
,
"frequency"
,
"first_release_last_commit"
,
"last_release_last_commit"
,
"first_release_short_version"
,
"last_release_short_version"
],
"properties"
:
{
"id"
:
{
"type"
:
"string"
},
"first_seen"
:
{
"type"
:
"string"
,
"format"
:
"date-time"
},
"last_seen"
:
{
"type"
:
"string"
,
"format"
:
"date-time"
},
"type"
:
{
"type"
:
"string"
},
"message"
:
{
"type"
:
"string"
},
"culprit"
:
{
"type"
:
"string"
},
"count"
:
{
"type"
:
"integer"
},
"external_url"
:
{
"type"
:
"string"
},
"external_base_url"
:
{
"type"
:
"string"
},
"user_count"
:
{
"type"
:
"integer"
},
"title"
:
{
"type"
:
"string"
},
"project_id"
:
{
"type"
:
"string"
},
"project_name"
:
{
"type"
:
"string"
},
"project_slug"
:
{
"type"
:
"string"
},
"short_id"
:
{
"type"
:
"string"
},
"status"
:
{
"type"
:
"string"
},
"frequency"
:
{
"type"
:
"array"
},
"first_release_last_commit"
:
{
"type"
:
[
"string"
,
"null"
]
},
"last_release_last_commit"
:
{
"type"
:
[
"string"
,
"null"
]
},
"first_release_short_version"
:
{
"type"
:
[
"string"
,
"null"
]
},
"last_release_short_version"
:
{
"type"
:
[
"string"
,
"null"
]
}
},
"additionalProperties"
:
false
}
spec/fixtures/api/schemas/error_tracking/error_stack_trace.json
0 → 100644
View file @
ae72d71d
{
"type"
:
"object"
,
"required"
:
[
"issue_id"
,
"stack_trace_entries"
,
"date_received"
],
"properties"
:
{
"issue_id"
:
{
"type"
:
[
"string"
,
"integer"
]
},
"stack_trace_entries"
:
{
"type"
:
"object"
},
"date_received"
:
{
"type"
:
"string"
}
},
"additionalProperties"
:
false
}
spec/fixtures/api/schemas/error_tracking/issue_detailed.json
0 → 100644
View file @
ae72d71d
{
"type"
:
"object"
,
"required"
:
[
"error"
],
"properties"
:
{
"error"
:
{
"$ref"
:
"error_detailed.json"
}
},
"additionalProperties"
:
false
}
spec/fixtures/api/schemas/error_tracking/issue_stack_trace.json
0 → 100644
View file @
ae72d71d
{
"type"
:
"object"
,
"required"
:
[
"error"
],
"properties"
:
{
"error"
:
{
"$ref"
:
"error_stack_trace.json"
}
},
"additionalProperties"
:
false
}
spec/helpers/application_settings_helper_spec.rb
View file @
ae72d71d
...
...
@@ -38,7 +38,7 @@ describe ApplicationSettingsHelper do
it_behaves_like
'when HTTP protocol is in use'
,
'http'
context
'with tracking parameters'
do
it
{
expect
(
visible_attributes
).
to
include
(
*
%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_
site
_id)
)
}
it
{
expect
(
visible_attributes
).
to
include
(
*
%i(snowplow_collector_hostname snowplow_cookie_domain snowplow_enabled snowplow_
app
_id)
)
}
it
{
expect
(
visible_attributes
).
to
include
(
*
%i(pendo_enabled pendo_url)
)
}
end
...
...
spec/lib/gitlab/ci/config/entry/default_spec.rb
View file @
ae72d71d
...
...
@@ -26,7 +26,7 @@ describe Gitlab::Ci::Config::Entry::Default do
it
'contains the expected node names'
do
expect
(
described_class
.
nodes
.
keys
)
.
to
match_array
(
%i[before_script image services
after_script cache]
)
after_script cache
interruptible
]
)
end
end
end
...
...
spec/lib/gitlab/ci/config/entry/job_spec.rb
View file @
ae72d71d
...
...
@@ -24,7 +24,7 @@ describe Gitlab::Ci::Config::Entry::Job do
let
(
:result
)
do
%i[before_script script stage type after_script cache
image services only except rules needs variables artifacts
environment coverage retry]
environment coverage retry
interruptible
]
end
it
{
is_expected
.
to
match_array
result
}
...
...
spec/lib/gitlab/ci/yaml_processor_spec.rb
View file @
ae72d71d
...
...
@@ -108,6 +108,25 @@ module Gitlab
it
{
expect
(
subject
[
:interruptible
]).
to
be_falsy
}
end
it
"returns interruptible when overridden for job"
do
config
=
YAML
.
dump
({
default:
{
interruptible:
true
},
rspec:
{
script:
"rspec"
}
})
config_processor
=
Gitlab
::
Ci
::
YamlProcessor
.
new
(
config
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
size
).
to
eq
(
1
)
expect
(
config_processor
.
stage_builds_attributes
(
"test"
).
first
).
to
eq
({
stage:
"test"
,
stage_idx:
2
,
name:
"rspec"
,
options:
{
script:
[
"rspec"
]
},
interruptible:
true
,
allow_failure:
false
,
when:
"on_success"
,
yaml_variables:
[]
})
end
end
describe
'retry entry'
do
...
...
spec/lib/gitlab/tracking_spec.rb
View file @
ae72d71d
...
...
@@ -8,7 +8,7 @@ describe Gitlab::Tracking do
stub_application_setting
(
snowplow_enabled:
true
)
stub_application_setting
(
snowplow_collector_hostname:
'gitfoo.com'
)
stub_application_setting
(
snowplow_cookie_domain:
'.gitfoo.com'
)
stub_application_setting
(
snowplow_
site
_id:
'_abc123_'
)
stub_application_setting
(
snowplow_
app
_id:
'_abc123_'
)
stub_application_setting
(
snowplow_iglu_registry_url:
'https://example.org'
)
end
...
...
spec/migrations/fill_productivity_analytics_start_date_spec.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
require
'spec_helper'
require
Rails
.
root
.
join
(
'db'
,
'migrate'
,
'20191004081520_fill_productivity_analytics_start_date.rb'
)
describe
FillProductivityAnalyticsStartDate
,
:migration
do
let
(
:settings_table
)
{
table
(
'application_settings'
)
}
let
(
:metrics_table
)
{
table
(
'merge_request_metrics'
)
}
before
do
settings_table
.
create!
end
context
'with NO productivity analytics data available'
do
it
'sets start_date to NOW'
do
expect
{
migrate!
}.
to
change
{
settings_table
.
first
&
.
productivity_analytics_start_date
}.
to
(
be_like_time
(
Time
.
now
))
end
end
context
'with productivity analytics data available'
do
before
do
ActiveRecord
::
Base
.
transaction
do
ActiveRecord
::
Base
.
connection
.
execute
(
'ALTER TABLE merge_request_metrics DISABLE TRIGGER ALL'
)
metrics_table
.
create!
(
merged_at:
Time
.
parse
(
'2019-09-09'
),
commits_count:
nil
,
merge_request_id:
3
)
metrics_table
.
create!
(
merged_at:
Time
.
parse
(
'2019-10-10'
),
commits_count:
5
,
merge_request_id:
1
)
metrics_table
.
create!
(
merged_at:
Time
.
parse
(
'2019-11-11'
),
commits_count:
10
,
merge_request_id:
2
)
ActiveRecord
::
Base
.
connection
.
execute
(
'ALTER TABLE merge_request_metrics ENABLE TRIGGER ALL'
)
end
end
it
'set start_date to earliest merged_at value with PA data available'
do
expect
{
migrate!
}.
to
change
{
settings_table
.
first
&
.
productivity_analytics_start_date
}.
to
(
be_like_time
(
Time
.
parse
(
'2019-10-10'
)))
end
end
end
spec/requests/api/settings_spec.rb
View file @
ae72d71d
...
...
@@ -178,7 +178,7 @@ describe API::Settings, 'Settings' do
snowplow_collector_hostname:
"snowplow.example.com"
,
snowplow_cookie_domain:
".example.com"
,
snowplow_enabled:
true
,
snowplow_
site_id:
"site
_id"
,
snowplow_
app_id:
"app
_id"
,
snowplow_iglu_registry_url:
'https://example.com'
}
end
...
...
spec/requests/user_avatar_spec.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
require
'spec_helper'
describe
'Loading a user avatar'
do
let
(
:user
)
{
create
(
:user
,
:with_avatar
)
}
context
'when logged in'
do
# The exact query count will vary depending on the 2FA settings of the
# instance, group, and user. Removing those extra 2FA queries in this case
# may not be a good idea, so we just set up the ideal case.
before
do
stub_application_setting
(
require_two_factor_authentication:
true
)
login_as
(
create
(
:user
,
:two_factor
))
end
# One each for: current user, avatar user, and upload record
it
'only performs three SQL queries'
do
get
user
.
avatar_url
# Skip queries on first application load
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
{
get
user
.
avatar_url
}.
not_to
exceed_query_limit
(
3
)
end
end
context
'when logged out'
do
# One each for avatar user and upload record
it
'only performs two SQL queries'
do
get
user
.
avatar_url
# Skip queries on first application load
expect
(
response
).
to
have_gitlab_http_status
(
200
)
expect
{
get
user
.
avatar_url
}.
not_to
exceed_query_limit
(
2
)
end
end
end
spec/services/error_tracking/issue_details_service_spec.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
require
'spec_helper'
describe
ErrorTracking
::
IssueDetailsService
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:sentry_url
)
{
'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project'
}
let
(
:token
)
{
'test-token'
}
let
(
:result
)
{
subject
.
execute
}
let
(
:error_tracking_setting
)
do
create
(
:project_error_tracking_setting
,
api_url:
sentry_url
,
token:
token
,
project:
project
)
end
subject
{
described_class
.
new
(
project
,
user
)
}
before
do
expect
(
project
).
to
receive
(
:error_tracking_setting
).
at_least
(
:once
).
and_return
(
error_tracking_setting
)
project
.
add_reporter
(
user
)
end
describe
'#execute'
do
context
'with authorized user'
do
context
'when issue_details returns a detailed error'
do
let
(
:detailed_error
)
{
build
(
:detailed_error_tracking_error
)
}
before
do
expect
(
error_tracking_setting
)
.
to
receive
(
:issue_details
).
and_return
(
issue:
detailed_error
)
end
it
'returns the detailed error'
do
expect
(
result
).
to
eq
(
status: :success
,
issue:
detailed_error
)
end
end
include_examples
'error tracking service data not ready'
,
:issue_details
include_examples
'error tracking service sentry error handling'
,
:issue_details
include_examples
'error tracking service http status handling'
,
:issue_details
end
include_examples
'error tracking service unauthorized user'
include_examples
'error tracking service disabled'
end
end
spec/services/error_tracking/issue_latest_event_service_spec.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
require
'spec_helper'
describe
ErrorTracking
::
IssueLatestEventService
do
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:project
)
{
create
(
:project
)
}
let
(
:sentry_url
)
{
'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project'
}
let
(
:token
)
{
'test-token'
}
let
(
:result
)
{
subject
.
execute
}
let
(
:error_tracking_setting
)
do
create
(
:project_error_tracking_setting
,
api_url:
sentry_url
,
token:
token
,
project:
project
)
end
subject
{
described_class
.
new
(
project
,
user
)
}
before
do
expect
(
project
).
to
receive
(
:error_tracking_setting
).
at_least
(
:once
).
and_return
(
error_tracking_setting
)
project
.
add_reporter
(
user
)
end
describe
'#execute'
do
context
'with authorized user'
do
context
'when issue_latest_event returns an error event'
do
let
(
:error_event
)
{
build
(
:error_tracking_error_event
)
}
before
do
expect
(
error_tracking_setting
)
.
to
receive
(
:issue_latest_event
).
and_return
(
latest_event:
error_event
)
end
it
'returns the error event'
do
expect
(
result
).
to
eq
(
status: :success
,
latest_event:
error_event
)
end
end
include_examples
'error tracking service data not ready'
,
:issue_latest_event
include_examples
'error tracking service sentry error handling'
,
:issue_latest_event
include_examples
'error tracking service http status handling'
,
:issue_latest_event
end
include_examples
'error tracking service unauthorized user'
include_examples
'error tracking service disabled'
end
end
spec/services/error_tracking/list_issues_service_spec.rb
View file @
ae72d71d
...
...
@@ -37,93 +37,12 @@ describe ErrorTracking::ListIssuesService do
end
end
context
'when list_sentry_issues returns nil'
do
before
do
expect
(
error_tracking_setting
)
.
to
receive
(
:list_sentry_issues
).
and_return
(
nil
)
end
it
'result is not ready'
do
expect
(
result
).
to
eq
(
status: :error
,
http_status: :no_content
,
message:
'Not ready. Try again later'
)
end
end
context
'when list_sentry_issues returns error'
do
before
do
allow
(
error_tracking_setting
)
.
to
receive
(
:list_sentry_issues
)
.
and_return
(
error:
'Sentry response status code: 401'
,
error_type:
ErrorTracking
::
ProjectErrorTrackingSetting
::
SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE
)
end
it
'returns the error'
do
expect
(
result
).
to
eq
(
status: :error
,
http_status: :bad_request
,
message:
'Sentry response status code: 401'
)
end
end
context
'when list_sentry_issues returns error with http_status'
do
before
do
allow
(
error_tracking_setting
)
.
to
receive
(
:list_sentry_issues
)
.
and_return
(
error:
'Sentry API response is missing keys. key not found: "id"'
,
error_type:
ErrorTracking
::
ProjectErrorTrackingSetting
::
SENTRY_API_ERROR_TYPE_MISSING_KEYS
)
end
it
'returns the error with correct http_status'
do
expect
(
result
).
to
eq
(
status: :error
,
http_status: :internal_server_error
,
message:
'Sentry API response is missing keys. key not found: "id"'
)
end
end
include_examples
'error tracking service data not ready'
,
:list_sentry_issues
include_examples
'error tracking service sentry error handling'
,
:list_sentry_issues
include_examples
'error tracking service http status handling'
,
:list_sentry_issues
end
context
'with unauthorized user'
do
let
(
:unauthorized_user
)
{
create
(
:user
)
}
subject
{
described_class
.
new
(
project
,
unauthorized_user
)
}
it
'returns error'
do
result
=
subject
.
execute
expect
(
result
).
to
include
(
status: :error
,
message:
'Access denied'
,
http_status: :unauthorized
)
end
end
context
'with error tracking disabled'
do
before
do
error_tracking_setting
.
enabled
=
false
end
it
'raises error'
do
result
=
subject
.
execute
expect
(
result
).
to
include
(
status: :error
,
message:
'Error Tracking is not enabled'
)
end
end
end
describe
'#sentry_external_url'
do
let
(
:external_url
)
{
'https://sentrytest.gitlab.com/sentry-org/sentry-project'
}
it
'calls ErrorTracking::ProjectErrorTrackingSetting'
do
expect
(
error_tracking_setting
).
to
receive
(
:sentry_external_url
).
and_call_original
subject
.
external_url
end
include_examples
'error tracking service unauthorized user'
include_examples
'error tracking service disabled'
end
end
spec/services/error_tracking/list_projects_service_spec.rb
View file @
ae72d71d
...
...
@@ -127,7 +127,7 @@ describe ErrorTracking::ListProjectsService do
end
it
'returns error'
do
expect
(
result
).
to
include
(
status: :error
,
message:
'
access denied'
)
expect
(
result
).
to
include
(
status: :error
,
message:
'
Access denied'
,
http_status: :unauthorized
)
end
end
...
...
spec/support/shared_examples/services/error_tracking_service_shared_examples.rb
0 → 100644
View file @
ae72d71d
# frozen_string_literal: true
shared_examples
'error tracking service data not ready'
do
|
service_call
|
context
"when
#{
service_call
}
returns nil"
do
before
do
expect
(
error_tracking_setting
)
.
to
receive
(
service_call
).
and_return
(
nil
)
end
it
'result is not ready'
do
expect
(
result
).
to
eq
(
status: :error
,
http_status: :no_content
,
message:
'Not ready. Try again later'
)
end
end
end
shared_examples
'error tracking service sentry error handling'
do
|
service_call
|
context
"when
#{
service_call
}
returns error"
do
before
do
allow
(
error_tracking_setting
)
.
to
receive
(
service_call
)
.
and_return
(
error:
'Sentry response status code: 401'
,
error_type:
ErrorTracking
::
ProjectErrorTrackingSetting
::
SENTRY_API_ERROR_TYPE_NON_20X_RESPONSE
)
end
it
'returns the error'
do
expect
(
result
).
to
eq
(
status: :error
,
http_status: :bad_request
,
message:
'Sentry response status code: 401'
)
end
end
end
shared_examples
'error tracking service http status handling'
do
|
service_call
|
context
"when
#{
service_call
}
returns error with http_status"
do
before
do
allow
(
error_tracking_setting
)
.
to
receive
(
service_call
)
.
and_return
(
error:
'Sentry API response is missing keys. key not found: "id"'
,
error_type:
ErrorTracking
::
ProjectErrorTrackingSetting
::
SENTRY_API_ERROR_TYPE_MISSING_KEYS
)
end
it
'returns the error with correct http_status'
do
expect
(
result
).
to
eq
(
status: :error
,
http_status: :internal_server_error
,
message:
'Sentry API response is missing keys. key not found: "id"'
)
end
end
end
shared_examples
'error tracking service unauthorized user'
do
context
'with unauthorized user'
do
let
(
:unauthorized_user
)
{
create
(
:user
)
}
subject
{
described_class
.
new
(
project
,
unauthorized_user
)
}
it
'returns error'
do
result
=
subject
.
execute
expect
(
result
).
to
include
(
status: :error
,
message:
'Access denied'
,
http_status: :unauthorized
)
end
end
end
shared_examples
'error tracking service disabled'
do
context
'with error tracking disabled'
do
before
do
error_tracking_setting
.
enabled
=
false
end
it
'raises error'
do
result
=
subject
.
execute
expect
(
result
).
to
include
(
status: :error
,
message:
'Error Tracking is not enabled'
)
end
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