1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# frozen_string_literal: true
module Gitlab
module Database
module SchemaValidation
class TrackInconsistency
COLUMN_TEXT_LIMIT = 6144
def initialize(inconsistency, project, user)
@inconsistency = inconsistency
@project = project
@user = user
end
def execute
return unless Gitlab.com?
return refresh_issue if inconsistency_record.present?
result = ::Issues::CreateService.new(
container: project,
current_user: user,
params: params,
perform_spam_check: false).execute
track_inconsistency(result[:issue]) if result.success?
end
private
attr_reader :inconsistency, :project, :user
def track_inconsistency(issue)
schema_inconsistency_model.create!(
issue: issue,
object_name: inconsistency.object_name,
table_name: inconsistency.table_name,
valitador_name: inconsistency.type,
diff: inconsistency_diff
)
end
def params
{
title: issue_title,
description: description,
issue_type: 'issue',
labels: default_labels + group_labels
}
end
def issue_title
"New schema inconsistency: #{inconsistency.object_name}"
end
def description
<<~MSG
We have detected a new schema inconsistency.
**Table name:** #{inconsistency.table_name}\
**Object name:** #{inconsistency.object_name}\
**Validator name:** #{inconsistency.type}\
**Object type:** #{inconsistency.object_type}\
**Error message:** #{inconsistency.error_message}
**Structure.sql statement:**
```sql
#{inconsistency.structure_sql_statement}
```
**Database statement:**
```sql
#{inconsistency.database_statement}
```
**Diff:**
```diff
#{inconsistency.diff}
```
For more information, please contact the database team.
MSG
end
def group_labels
dictionary = YAML.safe_load(File.read(table_file_path))
dictionary['feature_categories'].to_a.filter_map do |feature_category|
Gitlab::Database::ConvertFeatureCategoryToGroupLabel.new(feature_category).execute
end
rescue Errno::ENOENT
[]
end
def default_labels
%w[database database-inconsistency-report type::maintenance severity::4]
end
def table_file_path
Rails.root.join(Gitlab::Database::GitlabSchema.dictionary_paths.first, "#{inconsistency.table_name}.yml")
end
def schema_inconsistency_model
Gitlab::Database::SchemaValidation::SchemaInconsistency
end
def refresh_issue
return if inconsistency_diff == inconsistency_record.diff # Nothing to refresh
note = ::Notes::CreateService.new(
inconsistency_record.issue.project,
user,
{ noteable_type: 'Issue', noteable: inconsistency_record.issue, note: description }
).execute
inconsistency_record.update!(diff: inconsistency_diff) if note.persisted?
end
def inconsistency_diff
@inconsistency_diff ||= inconsistency.diff.to_s.first(COLUMN_TEXT_LIMIT)
end
def inconsistency_record
@inconsistency_record ||= schema_inconsistency_model.with_open_issues.find_by(
object_name: inconsistency.object_name,
table_name: inconsistency.table_name,
valitador_name: inconsistency.type
)
end
end
end
end
end
|