errmine 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/errmine/notifier.rb +53 -10
- data/lib/errmine/version.rb +1 -1
- data/lib/errmine.rb +30 -7
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4f71e4d605d9ce77753b0ffdea51499feb507ecc8b65fc156890c04a86bad270
|
|
4
|
+
data.tar.gz: 2c1d3242c5daa6c66035e13a59f68c6a890156f9f48d7635a6d535c9762ba0bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc3955573efbb9a1cff490071a3678f3a2bc7a6c04469f15a253b44560d275b0c4a26e84cd41583e80f47e421f11cfaf0b0a74ee5238b33ec8b8df27bfa6a140
|
|
7
|
+
data.tar.gz: 06eef437876a00211d6ccceaac6d06dca2846e1a1526c595e531e341379e30b788ce63f38aab46d97ff2b139e67ebb5f5ef83b06e22093b8b5af2785effb8ede
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Errmine changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 (2025-12-24)
|
|
4
|
+
- [Feature] Add app name to issue title for easy identification when multiple apps report to the same Redmine project.
|
|
5
|
+
- [Feature] Include app_name in checksum calculation so same errors in different apps create separate issues.
|
|
6
|
+
- [Feature] Add `Errmine.create_issue` method for creating custom Redmine issues with arbitrary subject, description, tracker, project, and tags.
|
|
7
|
+
- [Feature] Add tags support via `tag_list` parameter for both exception reporting and custom issues.
|
|
8
|
+
- [Feature] Add `default_tags` configuration option for tags applied to all issues.
|
|
9
|
+
- [Maintenance] Update actions/checkout to v6 in CI.
|
|
10
|
+
|
|
3
11
|
## 0.1.1 (2025-12-23)
|
|
4
12
|
- [Fix] Fix file permissions for gem packaging.
|
|
5
13
|
- [Fix] Fix gemspec metadata duplicate URI warning.
|
data/lib/errmine/notifier.rb
CHANGED
|
@@ -62,6 +62,38 @@ module Errmine
|
|
|
62
62
|
@mutex.synchronize { @cache.clear }
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
+
# Creates a custom issue in Redmine
|
|
66
|
+
#
|
|
67
|
+
# @param subject [String] issue subject/title
|
|
68
|
+
# @param description [String] issue description (Textile format)
|
|
69
|
+
# @param options [Hash] optional overrides
|
|
70
|
+
# @option options [String] :project_id Redmine project identifier
|
|
71
|
+
# @option options [Integer] :tracker_id Redmine tracker ID
|
|
72
|
+
# @option options [Array<String>] :tags tags to add to the issue
|
|
73
|
+
# @return [Hash, nil] the created issue or nil on failure
|
|
74
|
+
def create_custom_issue(subject:, description:, **options)
|
|
75
|
+
uri = build_uri('/issues.json')
|
|
76
|
+
|
|
77
|
+
issue_data = {
|
|
78
|
+
project_id: options[:project_id] || config.project_id,
|
|
79
|
+
tracker_id: options[:tracker_id] || config.tracker_id,
|
|
80
|
+
subject: subject,
|
|
81
|
+
description: description
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
tags = build_tag_list(options[:tags])
|
|
85
|
+
issue_data[:tag_list] = tags unless tags.empty?
|
|
86
|
+
|
|
87
|
+
response = http_post(uri, { issue: issue_data })
|
|
88
|
+
return nil unless response
|
|
89
|
+
|
|
90
|
+
data = JSON.parse(response.body)
|
|
91
|
+
data['issue']
|
|
92
|
+
rescue JSON::ParserError => e
|
|
93
|
+
warn "[Errmine] Failed to parse response: #{e.message}"
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
96
|
+
|
|
65
97
|
private
|
|
66
98
|
|
|
67
99
|
# Returns the Errmine configuration
|
|
@@ -71,13 +103,23 @@ module Errmine
|
|
|
71
103
|
Errmine.configuration
|
|
72
104
|
end
|
|
73
105
|
|
|
106
|
+
# Builds a combined tag list from default tags and provided tags
|
|
107
|
+
#
|
|
108
|
+
# @param tags [Array<String>, nil] additional tags to include
|
|
109
|
+
# @return [Array<String>] combined unique tags
|
|
110
|
+
def build_tag_list(tags)
|
|
111
|
+
combined = config.default_tags.dup
|
|
112
|
+
combined.concat(Array(tags)) if tags
|
|
113
|
+
combined.uniq
|
|
114
|
+
end
|
|
115
|
+
|
|
74
116
|
# Generates an 8-character checksum for the exception
|
|
75
117
|
#
|
|
76
118
|
# @param exception [Exception]
|
|
77
119
|
# @return [String]
|
|
78
120
|
def generate_checksum(exception)
|
|
79
121
|
first_app_line = first_app_backtrace_line(exception)
|
|
80
|
-
data = "#{exception.class}:#{exception.message}:#{first_app_line}"
|
|
122
|
+
data = "#{config.app_name}:#{exception.class}:#{exception.message}:#{first_app_line}"
|
|
81
123
|
Digest::MD5.hexdigest(data)[0, 8]
|
|
82
124
|
end
|
|
83
125
|
|
|
@@ -167,16 +209,17 @@ module Errmine
|
|
|
167
209
|
subject = build_subject(checksum, 1, exception)
|
|
168
210
|
description = build_description(exception, context)
|
|
169
211
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
description: description
|
|
176
|
-
}
|
|
212
|
+
issue_data = {
|
|
213
|
+
project_id: config.project_id,
|
|
214
|
+
tracker_id: config.tracker_id,
|
|
215
|
+
subject: subject,
|
|
216
|
+
description: description
|
|
177
217
|
}
|
|
178
218
|
|
|
179
|
-
|
|
219
|
+
tags = build_tag_list(context[:tags])
|
|
220
|
+
issue_data[:tag_list] = tags unless tags.empty?
|
|
221
|
+
|
|
222
|
+
response = http_post(uri, { issue: issue_data })
|
|
180
223
|
return nil unless response
|
|
181
224
|
|
|
182
225
|
data = JSON.parse(response.body)
|
|
@@ -225,7 +268,7 @@ module Errmine
|
|
|
225
268
|
truncated = message.length > SUBJECT_MESSAGE_LENGTH ? "#{message[0, SUBJECT_MESSAGE_LENGTH]}..." : message
|
|
226
269
|
truncated = truncated.gsub(/[\r\n]+/, ' ').strip
|
|
227
270
|
|
|
228
|
-
"[#{checksum}][#{count}] #{exception.class}: #{truncated}"
|
|
271
|
+
"[#{config.app_name}][#{checksum}][#{count}] #{exception.class}: #{truncated}"
|
|
229
272
|
end
|
|
230
273
|
|
|
231
274
|
# Builds the issue description in Textile format
|
data/lib/errmine/version.rb
CHANGED
data/lib/errmine.rb
CHANGED
|
@@ -29,6 +29,9 @@ module Errmine
|
|
|
29
29
|
# @return [String] Application name shown in issues
|
|
30
30
|
attr_accessor :app_name
|
|
31
31
|
|
|
32
|
+
# @return [Array<String>] Default tags to add to all issues
|
|
33
|
+
attr_accessor :default_tags
|
|
34
|
+
|
|
32
35
|
# @return [Boolean] Whether notifications are enabled
|
|
33
36
|
attr_accessor :enabled
|
|
34
37
|
|
|
@@ -37,13 +40,14 @@ module Errmine
|
|
|
37
40
|
|
|
38
41
|
# Initializes configuration with defaults from environment variables
|
|
39
42
|
def initialize
|
|
40
|
-
@redmine_url
|
|
41
|
-
@api_key
|
|
42
|
-
@project_id
|
|
43
|
-
@tracker_id
|
|
44
|
-
@app_name
|
|
45
|
-
@
|
|
46
|
-
@
|
|
43
|
+
@redmine_url = ENV.fetch('ERRMINE_REDMINE_URL', nil)
|
|
44
|
+
@api_key = ENV.fetch('ERRMINE_API_KEY', nil)
|
|
45
|
+
@project_id = ENV['ERRMINE_PROJECT'] || 'bug-tracker'
|
|
46
|
+
@tracker_id = 1
|
|
47
|
+
@app_name = ENV['ERRMINE_APP_NAME'] || 'unknown'
|
|
48
|
+
@default_tags = []
|
|
49
|
+
@enabled = true
|
|
50
|
+
@cooldown = 300
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
# Checks if the configuration has required values
|
|
@@ -93,6 +97,25 @@ module Errmine
|
|
|
93
97
|
warn "[Errmine] Failed to notify: #{e.message}"
|
|
94
98
|
nil
|
|
95
99
|
end
|
|
100
|
+
|
|
101
|
+
# Creates a custom issue in Redmine
|
|
102
|
+
#
|
|
103
|
+
# @param subject [String] issue subject/title
|
|
104
|
+
# @param description [String] issue description (Textile format)
|
|
105
|
+
# @param options [Hash] optional keyword arguments
|
|
106
|
+
# @option options [String] :project_id Redmine project identifier
|
|
107
|
+
# @option options [Integer] :tracker_id Redmine tracker ID
|
|
108
|
+
# @option options [Array<String>] :tags tags to add to the issue
|
|
109
|
+
# @return [Hash, nil] the created issue or nil on failure
|
|
110
|
+
def create_issue(subject:, description:, **options)
|
|
111
|
+
return unless configuration.enabled
|
|
112
|
+
return unless configuration.valid?
|
|
113
|
+
|
|
114
|
+
Notifier.instance.create_custom_issue(subject: subject, description: description, **options)
|
|
115
|
+
rescue StandardError => e
|
|
116
|
+
warn "[Errmine] Failed to create issue: #{e.message}"
|
|
117
|
+
nil
|
|
118
|
+
end
|
|
96
119
|
end
|
|
97
120
|
end
|
|
98
121
|
|