Commit 30160961 authored by Robert Speicher's avatar Robert Speicher

Merge branch '38223-link-to-gitlab-commit-in-error-detail-page' into 'master'

Backend: Link to GitLab commit in error detail page

See merge request gitlab-org/gitlab!22174
parents e17b8656 35e7550d
......@@ -76,6 +76,9 @@ module Types
field :last_release_short_version, GraphQL::STRING_TYPE,
null: true,
description: "Release version the error was last seen"
field :gitlab_commit, GraphQL::STRING_TYPE,
null: true,
description: "GitLab commit SHA attributed to the Error based on the release version"
def first_seen
DateTime.parse(object.first_seen)
......
......@@ -113,9 +113,8 @@ module ErrorTracking
when 'list_issues'
sentry_client.list_issues(**opts.symbolize_keys)
when 'issue_details'
{
issue: sentry_client.issue_details(**opts.symbolize_keys)
}
issue = sentry_client.issue_details(**opts.symbolize_keys)
{ issue: add_gitlab_issue_details(issue) }
when 'issue_latest_event'
{
latest_event: sentry_client.issue_latest_event(**opts.symbolize_keys)
......@@ -140,6 +139,20 @@ module ErrorTracking
private
def add_gitlab_issue_details(issue)
issue.gitlab_commit = match_gitlab_commit(issue.first_release_version)
issue
end
def match_gitlab_commit(release_version)
return unless release_version
commit = project.repository.commit(release_version)
commit&.id
end
def handle_exceptions
yield
rescue Sentry::Client::Error => e
......
......@@ -8,6 +8,7 @@ module ErrorTracking
:external_url,
:first_release_last_commit,
:first_release_short_version,
:gitlab_commit,
:first_seen,
:frequency,
:gitlab_issue,
......
---
title: Add GitLab commit to error detail endpoint
merge_request: 22174
author:
type: added
......@@ -5711,6 +5711,11 @@ type SentryDetailedError {
"""
frequency: [SentryErrorFrequency!]!
"""
GitLab commit SHA attributed to the Error based on the release version
"""
gitlabCommit: String
"""
ID (global ID) of the error
"""
......
......@@ -15548,6 +15548,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "gitlabCommit",
"description": "GitLab commit SHA attributed to the Error based on the release version",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "id",
"description": "ID (global ID) of the error",
......
......@@ -893,6 +893,7 @@ Autogenerated return type of RemoveAwardEmoji
| `lastReleaseLastCommit` | String | Commit the error was last seen |
| `firstReleaseShortVersion` | String | Release version the error was first seen |
| `lastReleaseShortVersion` | String | Release version the error was last seen |
| `gitlabCommit` | String | GitLab commit SHA attributed to the Error based on the release version |
## SentryErrorFrequency
......
......@@ -12,10 +12,12 @@ module Gitlab
:external_url,
:first_release_last_commit,
:first_release_short_version,
:first_release_version,
:first_seen,
:frequency,
:gitlab_project,
:gitlab_commit,
:gitlab_issue,
:gitlab_project,
:id,
:last_release_last_commit,
:last_release_short_version,
......
......@@ -143,7 +143,7 @@ module Sentry
end
def map_to_detailed_error(issue)
Gitlab::ErrorTracking::DetailedError.new(
Gitlab::ErrorTracking::DetailedError.new({
id: issue.fetch('id'),
first_seen: issue.fetch('firstSeen', nil),
last_seen: issue.fetch('lastSeen', nil),
......@@ -159,15 +159,16 @@ module Sentry
short_id: issue.fetch('shortId', nil),
status: issue.fetch('status', nil),
frequency: issue.dig('stats', '24h'),
gitlab_issue: parse_gitlab_issue(issue.fetch('pluginIssues', nil)),
project_id: issue.dig('project', 'id'),
project_name: issue.dig('project', 'name'),
project_slug: issue.dig('project', 'slug'),
gitlab_issue: parse_gitlab_issue(issue.fetch('pluginIssues', nil)),
first_release_last_commit: issue.dig('firstRelease', 'lastCommit'),
last_release_last_commit: issue.dig('lastRelease', 'lastCommit'),
first_release_short_version: issue.dig('firstRelease', 'shortVersion'),
first_release_version: issue.dig('firstRelease', 'version'),
last_release_last_commit: issue.dig('lastRelease', 'lastCommit'),
last_release_short_version: issue.dig('lastRelease', 'shortVersion')
)
})
end
def extract_tags(issue)
......
......@@ -224,9 +224,11 @@ describe Projects::ErrorTrackingController do
let(:error) { build(:detailed_error_tracking_error) }
it 'returns an error' do
expected_error = error.as_json.except('first_release_version').merge({ 'gitlab_commit' => nil })
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)
expect(json_response['error']).to eq(expected_error)
end
it_behaves_like 'sets the polling header'
......
......@@ -34,6 +34,7 @@ FactoryBot.define do
last_release_last_commit { '9ad419c86' }
first_release_short_version { 'abc123' }
last_release_short_version { 'abc123' }
first_release_version { '123456' }
skip_create
end
......
{
"type": "object",
"required" : [
"required": [
"external_url",
"external_base_url",
"last_seen",
......@@ -18,9 +18,10 @@
"first_release_last_commit",
"last_release_last_commit",
"first_release_short_version",
"last_release_short_version"
"last_release_short_version",
"gitlab_commit"
],
"properties" : {
"properties": {
"id": { "type": "string" },
"first_seen": { "type": "string", "format": "date-time" },
"last_seen": { "type": "string", "format": "date-time" },
......@@ -30,13 +31,10 @@
"count": { "type": "integer" },
"external_url": { "type": "string" },
"external_base_url": { "type": "string" },
"user_count": { "type": "integer"},
"user_count": { "type": "integer" },
"tags": {
"type": "object",
"required" : [
"level",
"logger"
],
"required": ["level", "logger"],
"properties": {
"level": {
"type": "string"
......@@ -57,7 +55,8 @@
"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"] }
"last_release_short_version": { "type": ["string", "null"] },
"gitlab_commit": { "type": ["string", "null"] }
},
"additionalProperties": false
}
......@@ -30,6 +30,7 @@ describe GitlabSchema.types['SentryDetailedError'] do
lastReleaseLastCommit
firstReleaseShortVersion
lastReleaseShortVersion
gitlabCommit
]
is_expected.to have_graphql_fields(*expected_fields)
......
......@@ -263,6 +263,7 @@ describe Sentry::Client::Issue do
:last_release_last_commit | [:lastRelease, :lastCommit]
:first_release_short_version | [:firstRelease, :shortVersion]
:last_release_short_version | [:lastRelease, :shortVersion]
:first_release_version | [:firstRelease, :version]
end
with_them do
......
......@@ -210,6 +210,53 @@ describe ErrorTracking::ProjectErrorTrackingSetting do
end
end
describe '#issue_details' do
let(:issue) { build(:detailed_error_tracking_error) }
let(:sentry_client) { double('sentry_client', issue_details: issue) }
let(:commit_id) { '123456' }
let(:result) do
subject.issue_details
end
context 'when cached' do
before do
stub_reactive_cache(subject, issue, {})
synchronous_reactive_cache(subject)
expect(subject).to receive(:sentry_client).and_return(sentry_client)
end
it { expect(result).to eq(issue: issue) }
it { expect(result[:issue].first_release_version).to eq(commit_id) }
it { expect(result[:issue].gitlab_commit).to eq(nil) }
context 'when release version is nil' do
before do
issue.first_release_version = nil
end
it { expect(result[:issue].gitlab_commit).to eq(nil) }
end
context 'when repo commit matches first relase version' do
let(:commit) { double('commit', id: commit_id) }
let(:repository) { double('repository', commit: commit) }
before do
expect(project).to receive(:repository).and_return(repository)
end
it { expect(result[:issue].gitlab_commit).to eq(commit_id) }
end
end
context 'when not cached' do
it { expect(subject).not_to receive(:sentry_client) }
it { expect(result).to be_nil }
end
end
describe '#update_issue' do
let(:opts) do
{ status: 'resolved' }
......
......@@ -56,6 +56,7 @@ describe 'getting a detailed sentry error' do
expect(error_data['status']).to eql sentry_detailed_error.status.upcase
expect(error_data['firstSeen']).to eql sentry_detailed_error.first_seen
expect(error_data['lastSeen']).to eql sentry_detailed_error.last_seen
expect(error_data['gitlabCommit']).to be nil
end
it 'is expected to return the frequency correctly' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment